<template>
  <view class="x-uploader" :class="{border: border}">
    <view v-if="props.title" class="title" style="position: relative">
      <view style="width: 12rpx;color: red;position: absolute;left: 4px;">
        <text v-if="props.required">*</text>
      </view>
      <text style="margin-left: 10rpx">{{ props.title }}</text>
    </view>
    <view style="padding: 0 10rpx;box-sizing: border-box" v-if="(props.media == 'file' || props.media == 'all') && props.limit != -1 && fileList.length < limit && !props.readonly" @click="onChoose">
      <slot>
        <button size="mini" style="background-color: #4C9DFB;" type="primary">{{ props.text }}</button>
      </slot>
    </view>
    <view :class="{'x-row': props.media == 'image'}">
      <slot name="preview">
        <x-file-view
            :size="props.size"
            :disabled="props.readonly"
            :mode="viewMode"
            @remove="onRemove"
            @preview="onPreview"
            :list="fileList">
              <view slot="text">
                <slot name="text"></slot>
              </view>
              <view slot="suffix" @click="onChoose" v-if="props.media == 'image' && props.limit != -1 && fileList.length < props.limit && !props.readonly">
                <slot>
                  <view class="image-box">
                    <uni-icons type="plusempty" size="30"></uni-icons>
                  </view>
                </slot>
              </view>
        </x-file-view>
      </slot>

    </view>

    <!--  选择文件类型弹窗  -->
    <view style="position: fixed;z-index: 999">
      <x-popup v-model="show" title="上传附件格式" :height="600">
        <view class="popup-view">
          <view class="select-file">
            <view class="select-view">
              <view class="file-view" @tap="chooseFile('image')">
                <image :src="`${publicPath}/img.png`" class="select-img"></image>
                <view class="text">上传图片</view>
              </view>
            </view>
            <view class="select-view">
              <view class="file-view" @tap="chooseFile('file')">
                <image :src="`${publicPath}/file.png`" class="select-img"></image>
                <view class="text">上传文件</view>
              </view>
            </view>
          </view>
        </view>
      </x-popup>
    </view>

  </view>
</template>

<script setup>
import XPopup from '@/components/lib/popup';
import Uploader from "./uploader";
import XFileView from "./fileView";

import Helper from "@/core/helper";
import Msg from "@/core/plugin/msg";


const props = defineProps({
  title: {
    type: String,
    default: ''
  },

  size:{
    type: String,
    default: '145',
  },

  required: {
    type: Boolean,
    default: true
  },

  accept: {
    type: [String, Array],
    default: "png,jpg,jpeg",
  },

  limit: {
    type: [Number, String],
    default: 1,
  },

  limitSize: {
    type: Number,
    default: 1024 * 1024 * 10
  },

  media: {
    type: String, //all imagae, file
    default: "image",
  },

  readonly: {
    type: Boolean,
    default: false,
  },

  url: {
    type: String,
    default: "/file/upload"
  },

  formData: {
    type: Object,
    default: () => {
      return {}
    }
  },
  business: {
    type: String,
    default: 'default'
  },

  modelValue: {
    type: [Array, String],
    default: () => {
      return [];
    }
  },

  text:{
    type: String,
    default:'选择文件',
  },

  mode: {
    type: String,
    default: 'list'
  },

  border: {
    type: Boolean,
    default: false
  },
  isAutoUpload: {
    type: Boolean,
    default: true
  },

  onlyCamera:{
    type: Boolean,
    default: false,
  }
})


import {computed, getCurrentInstance, ref, toRaw, toRef} from "vue"
const _this = getCurrentInstance()

const viewMode = computed(()=>{
  if(_this.slots.text) {
    return 'custom';
  }

  return props.media === 'image' ? 'grid' : props.mode;
})

const emit = defineEmits([
    'update:modelValue',
    'preview',
    'success',
    'change',
    'remove'
])

const show = ref(false)

const fileList = ref([])

const uploader = new Uploader()

import {watch} from "vue"

import {isProxy, isRef} from "vue"
const handlerValue = (files)=> {
  fileList.value = files;
}

const onPreview = (url)=> {
  emit("preview", url)
}

const onChoose = ()=> {
  if(props.readonly) {
    return
  }

  if(fileList.value.length >= props.limit) {
    Msg.error(`最多选择${this.limit}个文件或图片`);
    return
  }

  if ((props.media === 'all')) {
    show.value = true;
    return;
  }
  chooseFile(props.media == 'image' ? 'image' : 'file');
}

const chooseFile = (type)=> {
  let count = props.limit - fileList.value.length;
  uploader.setType(type);
  if(props.onlyCamera) {
    uploader.setSourceType("camera")
  }

  uploader.setUrl(props.url)

  let formatData = Object.assign({}, props.formData, {business: props.business});
  uploader.setFormData(formatData);

  uploader.setCount(count);
  uploader.setAccept(props.accept);
  uploader.setLimitSize(props.limitSize)
  uploader.isAutoUpload(props.isAutoUpload)
  uploader.choose().next({
    before: (files) => {
      if(fileList.value.length > props.limit) {
        Msg.alert("温馨提示", "上传已超最大限制，只允许上传" + props.limit + "个文件");
        return false;
      }
      return true;
    },

    success: (file) => {
      fileList.value.push(file.path);
      emit('success', file, fileList.value);
      change(fileList.value, props.formData);
    },

    complete: (files, errorList) => {
      emit("complete", toRaw(files), fileList.value, props.formData);
      show.value = false;

      if(! Helper.emptyArray(errorList)) {
        if(errorList.length == 1) {
          let errorFile = errorList[0];
          Msg.alert("提示", `${errorFile.name}文件上传失败：${errorFile.resp.message}`);
          return;
        }

        Msg.alert("提示", "上传多个文件中存在上传失败的文件");
      }
    }
  })
}

const change = (files, formData)=> {
  emit("change", files, formData);
  if(props.limit == 1) {
    emit('update:modelValue', Helper.emptyArray(fileList.value) ? "" : fileList.value[0]);
  } else {
    emit('update:modelValue', fileList.value);
  }
}

const onRemove = (index, file, files)=> {
  if(index > -1) {
    fileList.value.splice(index, 1);
    emit("remove", index, props.formData);
    change(fileList.value, props.formData);
  }
}

watch(()=> props.modelValue, (value)=>{
  if(! Helper.empty(value) && ! Array.isArray(value)) {
    value = [value];
  }
  if(Helper.emptyArray(value)) {
    value = [];
  }

  let files = JSON.parse(JSON.stringify(toRaw(value)));
  handlerValue(files);
}, {deep: true, immediate: true})
</script>


<style lang="less" scoped>
.border {
  border-bottom: 1px solid #e9e9e9;
}
.x-uploader {
  background-color: #fff;

  .title {
    padding: 20rpx 10rpx;
    box-sizing: border-box;
  }

  .image-box {
    width: 145rpx;
    height: 145rpx;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1rpx solid #eaeaea;
    margin-right: 20rpx;
    margin-bottom: 20rpx;
  }
}

.popup-view {
  background: #fff;
  width: 750rpx;
  height: 600rpx;

  position: fixed;
  bottom: 0;

  .x-center {
    font-weight: 700;
    padding: 30rpx 0;
    border-bottom: 1rpx solid #EAEAEA;
  }

  .select-file {
    display: flex;
    justify-content: space-around;
    align-items: center;

    .hidden-upLoad {}

    .select-view {
      width: 300rpx;
      height: 400rpx;

      display: flex;
      justify-content: center;
      align-items: center;

      .file-view {
        width: 180rpx;
        height: 200rpx;

        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;

        .text {
          margin-top: 20rpx;
        }
      }

      .select-img {
        width: 150rpx;
        height: 150rpx;
      }
    }
  }
}
</style>
